-- Standard awesome library
local gears = require("gears")
local awful = require("awful")
awful.rules = require("awful.rules")
local tyrannical = require("tyrannical")
require("awful.autofocus")
-- Widget and layout library
local freedesktop = require("freedesktop")
local lain = require("lain")
local wibox = require("wibox")
-- Theme handling library
local beautiful = require("beautiful")
-- Notification library
local attachdrop = require("attachdrop")
local minitray = require("utils.minitray")
local menubar = require("menubar")
local hotkeys_popup = require("awful.hotkeys_popup").widget

-- {{{ Error handling
-- Check if awesome encountered an error during startup and fell back to
-- another config (This code will only ever execute for the fallback config)
if awesome.startup_errors then
  awful.util.spawn.with_shell("notify-send -u 'critical' " ..
                                "'Oops, there were errors during startup!'" ..
                                awesome.startup_errors
   )
end

-- Handle runtime errors after startup
do
    local in_error = false
    awesome.connect_signal("debug::error", function (err)
        -- Make sure we don't go into an endless error loop
        if in_error then return end
        in_error = true

        awful.util.spawn.with_shell("notify-send -u 'critical' " ..
                                      "'Oops, an error happened!'" ..
                                       err)

        in_error = false
    end)
end
-- }}}

-- {{{ Autostart applications
local function run_once(cmd)
  findme = cmd
  firstspace = cmd:find(" ")
  if firstspace then
    findme = cmd:sub(0, firstspace-1)
  end
  awful.spawn.with_shell(string.format("pgrep -u $USER -x %s > /dev/null || (%s)", findme, cmd))
end

run_once("clipit")
-- }}}

-- Variable Definitions
os.setlocale(os.getenv("LANG"))

-- Useful Paths
home = os.getenv("HOME")

local f = assert(io.popen('python2 -c "import os; print os.path.isdir(\'/media/data\')"'))
local ddir = f:read()
f:close()

datadir = home
datapart = "/home"
if ddir == "True" then
  datadir = "/media/data"
  datapart = datadir
end

confdir = home .. "/.config/awesome"
scriptdir = home .. "/.bin"
scr_res = "1920x1200"

-- Choose Your Theme
beautiful.init(confdir .. "/themes/Darkness/theme.lua")

-- This is used later as the default terminal and editor to run.
terminal = scriptdir .. "/durxvt -geometry 100x30 -name Terminal -icon " .. freedesktop.utils.lookup_icon({ icon='terminal' })
ddterminal = scriptdir .. "/durxvt -pe tabbedex -name Drop-Terminal -icon " .. freedesktop.utils.lookup_icon({ icon='tilda' })
eter = terminal .. " -geometry 140x42 -name emacs -icon " .. freedesktop.utils.lookup_icon({ icon='emacs' }) .. " -e " .. scriptdir .. "/demacs "
browser = "firefox"
fileman = "dolphin " .. datadir
cfileman = terminal .. " -title Ranger -icon " .. freedesktop.utils.lookup_icon({ icon='system-file-manager' }) .. " -e ranger " .. datadir
music = terminal .. " -geometry 110x30 -title Music -icon " .. freedesktop.utils.lookup_icon({ icon='cantata' }) .. " -e ncmpcpp "
net = "nmcli_dmenu"
chat = terminal .. " -title Chat -icon " .. freedesktop.utils.lookup_icon({ icon='pidgin'  })  ..  " -e weechat "
torrent = terminal .. " -title Torrent -icon " .. freedesktop.utils.lookup_icon({ icon='transmission' }) .. " -e rtorrent "
tmux = terminal .. " -title Tmux -icon " .. freedesktop.utils.lookup_icon({ icon='utilities-terminal' }) .. " -e tmux new -s arkhan "

-- Default modkey.
-- Usually, Mod4 is the key with a logo between Control and Alt.
-- If you do not like this or do not have such a key,
-- I suggest you to remap Mod4 to another key using xmodmap or other tools.
-- However, you can use another modifier like Mod1, but it may interact with others.
modkey = "Mod4"
altkey = "Mod1"

-- Table of layouts to cover with awful.layout.inc, order matters.
awful.layout.layouts = {
  awful.layout.suit.floating,
  awful.layout.suit.tile,
  awful.layout.suit.tile.left,
  awful.layout.suit.tile.bottom,
  awful.layout.suit.tile.top,
  awful.layout.suit.fair,
  awful.layout.suit.fair.horizontal,
  awful.layout.suit.spiral,
  awful.layout.suit.spiral.dwindle,
  awful.layout.suit.max,
  awful.layout.suit.max.fullscreen,
  awful.layout.suit.magnifier,
  awful.layout.suit.corner.nw,
}
-- }}}

-- {{{ Helper functions
local function client_menu_toggle_fn()
  local instance = nil

  return function ()
    if instance and instance.wibox.visible then
      instance:hide()
      instance = nil
    else
      instance = awful.menu.clients({ theme = { width = 250 } })
    end
  end
end
-- }}}

-- Tags Manage
tags = {}

-- First, set some settings
tyrannical.settings.block_children_focus_stealing = true
tyrannical.settings.group_children = true
tyrannical.settings.default_layout = awful.layout.suit.spiral.dwindle
tyrannical.settings.mwfact = 0.66

-- Setup some tags
tyrannical.tags = {
  { name = "www",
    init = true,
    exclusive = true,
    screen = {1, 2},
    select = true,
    class = {
      "Opera", "Firefox", "Iceweasel", "Light",
      "Midori", "Rekonq", "Dillo", "qutebrowser",
      "Arora", "Iron", "Chromium",
      "Google-chrome-stable", "google-chrome", "nightly",
      "minefield", "google-chrome-unstable"
    }
  },
  { name = "mail",
    init = false,
    exclusive = true,
    screen = 1,
    class = {
      "Kmail", "Kmail:New", "Kmail:Re",
      "Akonadi_imap_resource", "evolution", "Icedove",
      "Icedove:Re", "Thunderbird", "Thunderbird:Re",
    }
  },
  { name = "files",
    init = false,
    exclusive = true,
    screen = 1,
    class = {
      "Thunar", "Konqueror", "Dolphin",
      "ark", "Nautilus","emelfm",
      "Dolphin:Copy",
    }
  },
  { name = "chat",
    init = false,
    exclusive = true,
    screen = 1,
    class = {
      "URxvt:Chat", "Telegram", "Skype",
      "qTox", "Cutegram", "TelegramDesktop"
    }
  },
  { name = "dev",
    init = false,
    exclusive = true,
    screen = 1,
    class = {
      "Kate", "KDevelop", "Codeblocks",
      "Code::Blocks" , "DDD", "kate4",
      "Geany", "jetbrains-pychar", "jetbrains-pycharm",
      "jetbrains-pycharm-ce", "jetbrains-pycharm-ce", "Atom",
      "Sqlectron"
    }
  },
  { name = "doc",
    init = false,
    exclusive = true,
    screen = 1,
    class = {
      "Assistant", "Okular", "Evince",
      "EPDFviewer", "xpdf", "Xpdf",
      "Zathura", "Kile", "TeXstudio"
    }
  },
  { name = "office",
    init = false,
    exclusive = true,
    screen = {1, 2},
    class = {
      "N/A", "LibreOffice 5.0", "libreoffice-startcenter",
      "libreoffice-writer", "libreoffice-calc", "libreoffice-impress",
      "libreoffice-base", "libreoffice-math", "libreoffice-draw",
      "com-almworks-launcher-Launcher", "OOWriter", "OOCalc",
      "OOMath", "OOImpress", "OOBase",
      "SQLitebrowser", "Silverun", "Workbench",
      "KWord", "KSpread", "KPres","Basket",
      "openoffice.org", "OpenOffice.*",
    }
  },
  { name = "media",
    init = false,
    exclusive = true,
    screen = 1,
    class = {
      "URxvt:MPD", "Cantata",
    }
  },
  { name = "conf",
    init = false ,
    exclusive = false,
    screen = 1,
    class = {
      "Systemsettings", "Kcontrol", "gconf-editor",
      "Lxappearance", "Kwalletd"
    }
  },
  { name = "download",
    init = false ,
    exclusive = false,
    screen = 1,
    class = {
      "JDownloader", "URxvt:Torrent"
    }
  },
  { name = "fullscreen",
    init = false ,
    exclusive = false,
    screen = 1,
    layout = awful.layout.suit.max.fullscreen,
    class = {
      "Plugin-container"
    }
  },
  { name = "movie",
    init = false,
    exclusive = false,
    screen = {1, 2},
    class = {
      "MPV:Movie"
    }
  }
}

-- Ignore the tag "exclusive" property for the following clients (matched by classes)
tyrannical.properties.intrusive = {
  "xterm", "urxvt", "aterm",
  "URxvt", "XTerm", "konsole",
  "terminator", "gnome-terminal", "URxvt:Terminal",
  "URxvt:Drop", "URxvt:Tmux", "XTerm:Terminal",
  "Emacs", "Pilasengine", "URxvt:Emacs",
  "emacsclient", "Kamerka", "Keepassx2",
  "ksnapshot", "pinentry", "gtksu",
  "kcalc", "xcalc", "feh",
  "Gradient editor", "About KDE", "Paste Special",
  "Background color", "kcolorchooser", "plasmoidviewer",
  "Xephyr", "kruler", "plasmaengineexplorer",
}

-- Ignore the tiled layout for the matching clients
tyrannical.properties.floating = {
  "xterm", "urxvt", "aterm",
  "URxvt", "XTerm", "konsole",
  "terminator", "gnome-terminal", "URxvt:Terminal",
  "URxvt:Drop", "URxvt:Tmux", "URxvt:MPD",
  "XTerm:Terminal", "Kmail:New", "Kmail:Re",
  "Dolphin:Move", "Dolphin:Copy", "Icedove:Re",
  "DownThemAll!", "Keepassx2", "Pilasengine",
  "URxvt:Emacs", "emacsclient", "URxvt:Torrent",
  "Kamerka", "MPlayer", "pinentry",
  "ksnapshot", "pinentry", "gtksu",
  "xine", "feh", "kmix",
  "kcalc", "xcalc", "yakuake",
  "Select Color$", "kruler", "kcolorchooser",
  "Paste Special", "New Form" , "Insert Picture",
  "kcharselect", "mythfrontend" , "plasmoidviewer",
  "Thunderbird:Re", "Emacs"
}

-- Make the matching clients (by classes) on top of the default layout
tyrannical.properties.ontop = {
  "Xephyr", "ksnapshot" , "kruler",
}

-- Force the matching clients (by classes) to be centered on the screen on init
tyrannical.properties.centered = {
  "kcalc", "MPV:Movie", "URxvt:Terminal",
  "URxvt:Chat", "XTerm:Terminal", "URxvt:MPD",
  "URxvt:Tmux", "Dolphin:Move", "Dolphin:Copy",
  "Kmail:New", "URxvt:Torrent", "Kmail:Re",
  "Kamerka", "URxvt:Emacs", "emacsclient",
  "Icedove:Re", "DownThemAll!", "Cutegram",
  "Keepassx2", "Thunderbird:Re", "Emacs"
}
-- Do not honor size hints request for those classes
tyrannical.properties.size_hints_honor = {
  xterm = false,
  URxvt = false,
  aterm = false,
  sauer_client = false,
  mythfrontend  = false
}

-- Menu
require("utils.menu")

-- Menubar configuration
menubar.utils.terminal = terminal -- Set the terminal for applications that require it
-- }}}

-- Widgets
-- markup
markup	= lain.util.markup
gray 	= beautiful.fg_normal
white	= beautiful.fg_focus
red	= "#EB8F8F"
green	= "#8FEB8F"

-- Clock & Date
-- Textclock
local mytextclock = wibox.widget.textclock(
  markup(gray, "%a") ..
     markup(white, " %d ") ..
     markup(gray, "%b ") ..
     markup(white, "%H:%M ")
)
mytextclock.font = beautiful.font


-- Calendar
lain.widget.calendar({
    cal = scriptdir .. "/agenda",
    attach_to = { mytextclock },
    notification_preset = {
      font = beautiful.widget_font,
      fg   = white,
      bg   = "#121212"
    }
})

-- data fs
local fs = lain.widget.fs({
      partition = datapart,
      options = "--exclude-type=tmpfs",
      notification_preset = {
         fg = white,
         bg = "#121212",
         font = beautiful.widget_font },
      settings  = function()
         fs_header = " Hdd "
         fs_p      = fs_now.used .. "% "
         widget:set_markup(markup.font(beautiful.font, markup(gray, fs_header) .. markup(white, fs_p)))
      end
})

-- ALSA volume
local volume = lain.widget.alsa({
    settings = function()
       header = "Vol "
       vlevel  = volume_now.level

       if volume_now.status == "off" then
         vlevel = vlevel .. "M "
       else
        vlevel = vlevel .. "% "
       end
       widget:set_markup(markup.font(beautiful.font, markup(gray, header) .. markup(white, vlevel)))
    end
})

-- MPD
local f = assert(io.popen("cat ~/.config/mpd/mpd.conf | grep -v '#' | grep 'music_directory' | cut -d ' ' -f2 | awk '{print $2}' | sed 's/\"//g'"))
local dir = f:read()
f:close()
local mpdwidget = lain.widget.mpd({
    music_dir = dir,
    settings = function()
      mpd_notification_preset = {
        text = string.format(
          "%s [%s] - %s\n%s", mpd_now.artist,
          mpd_now.album, mpd_now.date, mpd_now.title
        )
      }
      if mpd_now.state == "play" then
        artist = mpd_now.artist .. " > "
        title  = mpd_now.title .. " "
      elseif mpd_now.state == "pause" then
        artist = "mpd "
        title  = "paused "
      else
        artist = ""
        title  = ""
      end
      widget:set_markup(markup(white, artist) .. markup(gray, title))
  end
})

-- Net Info
local wifiwidget = lain.widget.watch({
      cmd = "iwgetid -r",
      settings = function()
        if output ~= nil and output ~= '' then
          widget:set_markup(output)
        else
          widget:set_markup('')
        end
      end
})

wifiwidget.widget:buttons(awful.util.table.join(
                            awful.button({ }, 1, function ()
                                local f = assert(io.popen("iwgetid -ar"))
                                local wifiaccesspoint = f:read()
                                f:close()
                                local f = io.popen("ip link show | cut -d' ' -f2,9")
                                local ws = f:read("*a")
                                f:close()
                                local ws = ws:match("%w+: UP")
                                f = assert(io.popen("iwconfig ".. ws:gsub(": UP", "") .." | grep 'Link Quality' | awk '{print $2}' | awk -F'=' '{print $2}'"))
                                local wifiquality = f:read()
                                f:close()
                                f = io.popen("ip addr | grep 'inet ' | grep -v '127.0.0.1' | cut -d ':' -f2 | awk '{print $2}'")
                                local ipaddress = f:read()
                                f:close()
                                awful.util.spawn.with_shell("notify-send -u 'normal' " ..
                                                              "'IP: '" .. ipaddress .. "'\n'" ..
                                                              "'Access Point: '" .. wifiaccesspoint .. "'\n'" ..
                                                              "'Link Quality: '" .. wifiquality)
end)))


-- Net

local netwidget = lain.widget.net({
      settings = function()
         widget:set_markup(
            markup(white, " " .. net_now.received)
               .. " /" ..
               markup(white, " " .. net_now.sent))
      end
})

netwidget.widget:buttons(awful.util.table.join(
                            awful.button({ }, 1, function () os.execute(net) end)
))

-- Battery
local bat = lain.widget.bat({
    settings = function()
      widget:set_markup(markup.font(beautiful.font, ""))
      if bat_now.status ~= "N/A" then
        bat_header = " Bat "
        bat_p      = bat_now.perc .. "% "
        widget:set_markup(markup.font(beautiful.font, markup(gray, bat_header) .. markup(white, bat_p)))
      end
    end
})

-- Spacers
space = wibox.widget.textbox()
space:set_text(' ')
-- }}}

-- Create a wibox for each screen and add it
local taglist_buttons = awful.util.table.join(
   awful.button({ }, 1, function(t) t:view_only() end),
   awful.button({ modkey }, 1, function(t)
         if client.focus then
            client.focus:move_to_tag(t)
         end
   end),
   awful.button({ }, 3, awful.tag.viewtoggle),
   awful.button({ modkey }, 3, function(t)
         if client.focus then
            client.focus:toggle_tag(t)
         end
   end),
   awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
   awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
)

local tasklist_buttons = awful.util.table.join(
   awful.button({ }, 1, function (c)
       if c == client.focus then
         c.minimized = true
       else
         -- Without this, the following
         -- :isvisible() makes no sense
         c.minimized = false
         if not c:isvisible() and c.first_tag then
           c.first_tag:view_only()
         end
         -- This will also un-minimize
         -- the client, if needed
         client.focus = c
         c:raise()
         end
   end),
   awful.button({ }, 3, client_menu_toggle_fn()),
   awful.button({ }, 4, function ()
       awful.client.focus.byidx(1)
   end),
   awful.button({ }, 5, function ()
       qawful.client.focus.byidx(-1)
end))

local function set_wallpaper(s)
   -- Wallpaper
    if beautiful.wallpaper then
        local wallpaper = beautiful.wallpaper
        -- If wallpaper is a function, call it with the screen
        if type(wallpaper) == "function" then
            wallpaper = wallpaper(s)
        end
        gears.wallpaper.maximized(wallpaper, s, true)
    end
end

local function update_txt_layoutbox(s)
    -- Writes a string representation of the current layout in a textbox widget
    local txt_l = beautiful["layout_txt_" .. awful.layout.getname(awful.layout.get(s))] or ""
    s.mytxtlayoutbox:set_text(txt_l)
end

-- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
screen.connect_signal("property::geometry", set_wallpaper)

awful.screen.connect_for_each_screen(function(s)

    -- Wallpaper
    set_wallpaper(s)

    -- Create a promptbox for each screen
    s.mypromptbox = awful.widget.prompt()

    -- Textual layoutbox
    s.mytxtlayoutbox = wibox.widget.textbox(beautiful["layout_txt_" .. awful.layout.getname(awful.layout.get(s))])
    awful.tag.attached_connect_signal(s, "property::selected", function () update_txt_layoutbox(s) end)
    awful.tag.attached_connect_signal(s, "property::layout", function () update_txt_layoutbox(s) end)
    s.mytxtlayoutbox:buttons(awful.util.table.join(
                           awful.button({ }, 1, function () awful.layout.inc( 1) end),
                           awful.button({ }, 3, function () awful.layout.inc(-1) end),
                           awful.button({ }, 4, function () awful.layout.inc( 1) end),
						   awful.button({ }, 5, function () awful.layout.inc(-1) end)))

    -- Create a taglist widget
    s.mytaglist = awful.widget.taglist(s, awful.widget.taglist.filter.all, taglist_buttons)

    -- Create a tasklist widget
    s.mytasklist = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, tasklist_buttons)

    -- Create the wibox
    s.mywibox = awful.wibar({ position = "top", screen = s, height = 18 })

    -- Add widgets to the wibox
    s.mywibox:setup {
        layout = wibox.layout.align.horizontal,
        { -- Left widgets
            layout = wibox.layout.fixed.horizontal,
            s.mytxtlayoutbox,
            space,
            s.mytaglist,
            space,
            s.mypromptbox,
            space,
        },
        space,
        {-- Right widgets
           layout = wibox.layout.fixed.horizontal,
           wifiwidget,
           netwidget,
           fs.widget,
           bat.widget,
           volicon,
           volume.widget,
           mytextclock,
        },
    }
end)
-- }}}

-- {{{ Mouse bindings
-- @DOC_ROOT_BUTTONS@
root.buttons(awful.util.table.join(
               awful.button({ }, 3, function () mymainmenu:toggle() end),
               awful.button({ }, 4, awful.tag.viewnext),
               awful.button({ }, 5, awful.tag.viewprev)
))
-- }}}

-- {{{ Key bindings
-- @DOC_GLOBAL_KEYBINDINGS@
globalkeys = awful.util.table.join(
  awful.key({ modkey, "Shift"   }, "s",      hotkeys_popup.show_help,
    {description="show help", group="awesome"}),
  awful.key({ modkey,           }, "Left",   awful.tag.viewprev,
    {description = "view previous", group = "tag"}),
  awful.key({ modkey,           }, "Right",  awful.tag.viewnext,
    {description = "view next", group = "tag"}),
  awful.key({ modkey,           }, "Escape", awful.tag.history.restore,
    {description = "go back", group = "tag"}),

  awful.key({ modkey,           }, "j",
    function ()
      awful.client.focus.byidx( 1)
    end,
    {description = "focus next by index", group = "client"}
  ),
  awful.key({ modkey,           }, "k",
    function ()
      awful.client.focus.byidx(-1)
    end,
    {description = "focus previous by index", group = "client"}
  ),
  awful.key({ modkey,           }, "w", function () mymainmenu:show() end,
    {description = "show main menu", group = "awesome"}),

  -- Layout manipulation
  awful.key({ modkey, "Shift"   }, "j", function () awful.client.swap.byidx(  1)    end,
    {description = "swap with next client by index", group = "client"}),
  awful.key({ modkey, "Shift"   }, "k", function () awful.client.swap.byidx( -1)    end,
    {description = "swap with previous client by index", group = "client"}),
  awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end,
    {description = "focus the next screen", group = "screen"}),
  awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end,
    {description = "focus the previous screen", group = "screen"}),
  awful.key({ modkey,           }, "u", awful.client.urgent.jumpto,
    {description = "jump to urgent client", group = "client"}),
  awful.key({ modkey,           }, "Tab",
    function ()
      awful.client.focus.history.previous()
      if client.focus then
        client.focus:raise()
      end
    end,
    {description = "go back", group = "client"}),

  -- Show Open Window's
  awful.key({ altkey            }, "Tab",
    function ()
      menu = {
        theme = {
          width = 300,
          border = 1,
          border_color = beautiful.border_focus,
          bg_normal = "#121212"
        }
	    }
      menu.items = clsmenu()
      local m = awful.menu(menu)
      m:show()
  end),
	-- Show Open DropDown Terminal

  awful.key({ altkey, "Control" }, "Tab",
    function ()
      menu = {
	      theme = {
          width = 300,
          border = 1,
          border_color = beautiful.border_focus,
          bg_normal = "#121212"
	      }
      }
      menu.items = clsmenu_drop()
      local m = awful.menu(menu)
      m:show()
  end),

  -- Toggle Systray
  awful.key({ modkey,    }, "s", function() minitray.toggle() end ),

  -- Standard program
  awful.key({ modkey,           }, "Return", function () awful.spawn(terminal) end,
     {description = "open a terminal", group = "launcher"}),
  awful.key({ modkey,           }, "p",     function () awful.spawn(music)  end,
    {description = "Open ncmpcpp in a terminal", group = "music"}),
  awful.key({ modkey,           }, "t",     function () awful.spawn(fileman) end,
    {description = "Open default file manager inthis case Dolphin", group = "fileman"}),
  awful.key({ modkey,           }, "f",     function () awful.spawn(cfileman) end,
    {description = "Open terminal based file manager", group = "fileman"}),
  awful.key({ modkey,           }, "b",     function () awful.spawn(browser) end,
    {description = "Open prefer web browser", group = "web"}),
  awful.key({ modkey,           }, "i",     function () awful.spawn(chat) end,
    {description = "Open terminal based IM client", group = "IM"}),
  awful.key({ modkey,           }, "e",     function () awful.spawn(scriptdir .. "/demacs") end,
    {description = "Open emacsclient", group = "Emacs"}),
  awful.key({ modkey, "Control" }, "r", awesome.restart,
     {description = "reload awesome", group = "awesome"}),
  awful.key({ modkey, "Shift"   }, "q", awesome.quit,
     {description = "quit awesome", group = "awesome"}),

  -- Record a Screencast
  awful.key({ modkey,           }, "F7",      function() awful.spawn.with_shell(scriptdir .. "/startscreencast") end),
  awful.key({ modkey,           }, "F8",      function() awful.spawn.with_shell(scriptdir .. "/stopscreencast") end),

  -- Take a Screenshot
  awful.key({ modkey, "Shift"   }, "p",       function() awful.spawn.with_shell(scriptdir .. "/screenshot") end),

  -- attach terminal to F12
  awful.key({               }, "F12",
    function ()
      attachdrop.toggle(ddterminal, "left", "top", 0.8, 0.75)
  end),

  awful.key({ modkey,    }, "F12",
    function ()
      attachdrop.attach(ddterminal)
  end),

  -- Volume control
  awful.key({ altkey }, "Up",
    function ()
      os.execute("pamixer -i 1")
      volume.update()
  end),
  awful.key({ altkey }, "Down",
    function ()
      os.execute("pamixer -d 1")
      volume.update()
  end),
  awful.key({ altkey }, "m",
    function ()
      os.execute("pamixer -t")
      volume.update()
  end),
  awful.key({ altkey, "Control" }, "m",
    function ()
      os.execute("pamixer --allow-boost")
      volume.update()
  end),

  -- MPD control
  awful.key({ altkey, "Control" }, "Up",
    function ()
      awful.util.spawn.with_shell("mpc toggle || ncmpc toggle || pms toggle")
  end),

  awful.key({ altkey, "Control" }, "Down",
    function ()
      awful.util.spawn.with_shell("mpc stop || ncmpc stop || pms stop")
  end),
  awful.key({ altkey, "Control" }, "Left",
    function ()
      awful.util.spawn.with_shell("mpc prev || ncmpc prev || pms prev")
  end),
  awful.key({ altkey, "Control" }, "Right",
    function ()
      awful.spawn.with_shell("mpc next || ncmpc next || pms next")
  end),

  awful.key({ modkey,           }, "l",     function () awful.tag.incmwfact( 0.05)          end,
    {description = "increase master width factor", group = "layout"}),
  awful.key({ modkey,           }, "h",     function () awful.tag.incmwfact(-0.05)          end,
    {description = "decrease master width factor", group = "layout"}),
  awful.key({ modkey, "Shift"   }, "h",     function () awful.tag.incnmaster( 1, nil, true) end,
    {description = "increase the number of master clients", group = "layout"}),
  awful.key({ modkey, "Shift"   }, "l",     function () awful.tag.incnmaster(-1, nil, true) end,
    {description = "decrease the number of master clients", group = "layout"}),
  awful.key({ modkey, "Control" }, "h",     function () awful.tag.incncol( 1, nil, true)    end,
    {description = "increase the number of columns", group = "layout"}),
  awful.key({ modkey, "Control" }, "l",     function () awful.tag.incncol(-1, nil, true)    end,
    {description = "decrease the number of columns", group = "layout"}),
  awful.key({ modkey,           }, "space", function () awful.layout.inc( 1)                end,
    {description = "select next", group = "layout"}),
  awful.key({ modkey, "Shift"   }, "space", function () awful.layout.inc(-1)                end,
    {description = "select previous", group = "layout"}),

  awful.key({ modkey, "Control" }, "n",
    function ()
      local c = awful.client.restore()
      -- Focus restored client
      if c then
        client.focus = c
        c:raise()
      end
    end,
    {description = "restore minimized", group = "client"}),

  -- Prompt
  awful.key({ modkey            }, "r", function()
      os.execute('rofi -font "' .. beautiful.font .. '" -show run') end,
    {description = "run prompt", group = "launcher"}),

  awful.key({ modkey }, "x",
    function ()
      awful.prompt.run {
        prompt       = "Run Lua code: ",
        textbox      = awful.screen.focused().mypromptbox.widget,
        exe_callback = awful.util.eval,
        history_path = awful.util.get_cache_dir() .. "/history_eval"
      }
    end,
    {description = "lua execute prompt", group = "awesome"}),

  -- passmenu password copy to clipboard
  awful.key({ modkey }, ".",
    function()
      awful.spawn.with_shell(
        scriptdir .. "/passmenu 1 -p 'pass (password → clipboard):'")
    end,
    {description = "get passmenu password (clipboard)", group = "passwords"}),

  -- passmenu username copy to clipboard
  awful.key({ modkey }, ",",
    function()
      awful.spawn.with_shell(
        scriptdir .. "/passmenu 2 -p 'pass (username → clipboard):'")
    end,
    {description = "get passmenu username (clipboard)", group = "passwords"}),

  -- passmenu url copy to clipboard
  awful.key({ modkey }, ";",
    function()
      awful.spawn.with_shell(
        scriptdir .. "/passmenu 3 -p 'pass (url → clipboard):'")
    end,
    {description = "get passmenu url (clipboard)", group = "passwords"})
)

-- @DOC_CLIENT_KEYBINDINGS@
  clientkeys = awful.util.table.join(
    awful.key({ altkey, "Shift"   }, "m",      lain.util.magnify_client                         ),
    awful.key({ modkey, "Shift"   }, "f",
      function (c)
        c.fullscreen = not c.fullscreen
        c:raise()
      end,
      {description = "toggle fullscreen", group = "client"}),
    awful.key({ modkey, "Shift"   }, "c",      function (c) c:kill()                         end,
      {description = "close", group = "client"}),
    awful.key({ modkey, "Control" }, "space",  awful.client.floating.toggle                     ,
      {description = "toggle floating", group = "client"}),
    awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
      {description = "move to master", group = "client"}),
    awful.key({ modkey,           }, "o",      function (c) c:move_to_screen()               end,
      {description = "move to screen", group = "client"}),
    awful.key({ modkey,           }, "t",      function (c) c.ontop = not c.ontop            end,
      {description = "toggle keep on top", group = "client"}),
    awful.key({ modkey,           }, "n",
      function (c)
        -- The client currently has the input focus, so it cannot be
        -- minimized, since minimized clients can't have the focus.
        c.minimized = true
      end ,
      {description = "minimize", group = "client"}),
    awful.key({ modkey,           }, "m",
      function (c)
        c.maximized = not c.maximized
        c:raise()
      end ,
      {description = "maximize", group = "client"})
  )

  -- @DOC_NUMBER_KEYBINDINGS@
  -- Bind all key numbers to tags.
  -- Be careful: we use keycodes to make it work on any keyboard layout.
  -- This should map on the top row of your keyboard, usually 1 to 9.
  for i = 1, 9 do
    globalkeys = awful.util.table.join(globalkeys,
        -- View tag only.
        awful.key({ modkey }, "#" .. i + 9,
                  function ()
                        local screen = awful.screen.focused()
                        local tag = screen.tags[i]
                        if tag then
                           tag:view_only()
                        end
                  end,
                  {description = "view tag #"..i, group = "tag"}),
        -- Toggle tag display.
        awful.key({ modkey, "Control" }, "#" .. i + 9,
                  function ()
                      local screen = awful.screen.focused()
                      local tag = screen.tags[i]
                      if tag then
                         awful.tag.viewtoggle(tag)
                      end
                  end,
                  {description = "toggle tag #" .. i, group = "tag"}),
        -- Move client to tag.
        awful.key({ modkey, "Shift" }, "#" .. i + 9,
                  function ()
                      if client.focus then
                          local tag = client.focus.screen.tags[i]
                          if tag then
                              client.focus:move_to_tag(tag)
                          end
                     end
                  end,
                  {description = "move focused client to tag #"..i, group = "tag"}),
        -- Toggle tag on focused client.
        awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
                  function ()
                      if client.focus then
                          local tag = client.focus.screen.tags[i]
                          if tag then
                              client.focus:toggle_tag(tag)
                          end
                      end
                  end,
                  {description = "toggle focused client on tag #" .. i, group = "tag"})
    )
end

-- @DOC_CLIENT_BUTTONS@
clientbuttons = awful.util.table.join(
    awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
    awful.button({ modkey }, 1, awful.mouse.client.move),
    awful.button({ modkey }, 3, awful.mouse.client.resize))

-- Set keys
root.keys(globalkeys)
-- }}}

-- {{{ Rules
-- Rules to apply to new clients (through the "manage" signal).
-- @DOC_RULES@
awful.rules.rules = {
    -- @DOC_GLOBAL_RULE@
    -- All clients will match this rule.
    { rule = { },
      properties = { border_width = beautiful.border_width,
                     border_color = beautiful.border_normal,
                     focus = awful.client.focus.filter,
                     raise = true,
                     keys = clientkeys,
                     buttons = clientbuttons,
                     screen = awful.screen.preferred,
                     placement = awful.placement.no_overlap+awful.placement.no_offscreen
     }
    },

    -- @DOC_FLOATING_RULE@
    -- Floating clients.
    { rule_any = {
        instance = {
          "DTA",  -- Firefox addon DownThemAll.
          "copyq",  -- Includes session name in class.
        },
        class = {
          "Arandr",
          "Gpick",
          "Kruler",
          "MessageWin",  -- kalarm.
          "Sxiv",
          "Wpa_gui",
          "pinentry",
          "veromix",
          "xtightvncviewer"},

        name = {
          "Event Tester",  -- xev.
        },
        role = {
          "AlarmWindow",  -- Thunderbird's calendar.
          "pop-up",       -- e.g. Google Chrome's (detached) Developer Tools.
        }
    }, properties = { floating = true }},

    -- @DOC_DIALOG_RULE@
    -- Add titlebars to normal clients and dialogs
    { rule_any = {type = { "normal", "dialog" }
      }, properties = { titlebars_enabled = true }
    },
    { rule = { class = "URxvt", name = "Terminal" },
      callback = function (c)
         awful.client.property.set(c, "overwrite_class", "URxvt:Terminal")
      end
    },
    { rule = { class = "URxvt", name = "Drop-Terminal" },
      callback = function (c)
        awful.client.property.set(c, "overwrite_class", "URxvt:Drop")
      end
    },
    { rule = { class = "URxvt", name = "Ranger" },
      callback = function (c)
         c.name = "URxvt:Ranger"
      end
    },
    { rule = { class = "URxvt", name = "Tmux" },
      callback = function (c)
         awful.client.property.set(c, "overwrite_class", "URxvt:Tmux")
      end
    },
    { rule = { class = "URxvt", name = "Torrent" },
      callback = function (c)
         awful.client.property.set(c, "overwrite_class", "URxvt:Torrent")
      end
    },
    { rule = { class = "URxvt", name = "Chat" },
      callback = function (c)
         awful.client.property.set(c, "overwrite_class", "URxvt:Chat")
      end
    },
    { rule = { class = "URxvt", name = "Music" },
      callback = function (c)
        awful.client.property.set(c, "overwrite_class", "URxvt:MPD")
      end
    },
    { rule = { class = "URxvt", name = "emacs" },
      callback = function(c)
        awful.client.property.set(c, "overwrite_class", "URxvt:Emacs")
      end
    },
    { rule = { class = "XTerm" },
      callback = function (c)
         awful.client.property.set(c, "overwrite_class", "XTerm:Terminal")
      end
    },
    { rule = { class = "mpv" },
      callback = function (c)
         awful.client.property.set(c, "overwrite_class", "MPV:Movie")
      end
    },
    { rule = { class = "Kmail", name = "sin nombre" },
      callback = function (c)
        awful.client.property.set(c, "overwrite_class", "Kmail:New")
      end
    },
    { rule = { class = "Kmail", name = "Re:" },
      callback = function (c)
        awful.client.property.set(c, "overwrite_class", "Kmail:Re")
      end
    },

    { rule = { class = "Thunderbird", name = "Redacción: " },
      callback = function (c)
        awful.client.property.set(c, "overwrite_class", "Thunderbird:Re")
      end
    },

    { rule = { class = "Icedove", name = "Redacción: " },
      callback = function (c)
        awful.client.property.set(c, "overwrite_class", "Icedove:Re")
      end
    },

    { rule = { class = "Dolphin", name = "Copiando " },
      callback = function (c)
         awful.client.property.set(c, "overwrite_class", "Dolphin:Copy")
      end
    },

    { rule = { class = "Dolphin", name = "Moviendo " },
      callback = function (c)
         awful.client.property.set(c, "overwrite_class", "Dolphin:Move")
      end
    },

    -- Set Firefox to always map on the tag named "2" on screen 1.
    -- { rule = { class = "Firefox" },
    --   properties = { screen = 1, tag = "2" } },
}
-- }}}

-- {{{ Signals
-- Signal function to execute when a new client appears.
-- @DOC_MANAGE_HOOK@
client.connect_signal("manage", function (c)
    -- Set the windows at the slave,
    -- i.e. put it at the end of others instead of setting it master.
    -- if not awesome.startup then awful.client.setslave(c) end

    if awesome.startup and
      not c.size_hints.user_position
      and not c.size_hints.program_position then
        -- Prevent clients from being unreachable after screen count changes.
        awful.placement.no_offscreen(c)
    end
end)

-- Enable sloppy focus, so that focus follows mouse.
client.connect_signal("mouse::enter", function(c)
    if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
        and awful.client.focus.filter(c) then
        client.focus = c
    end
end)

-- @DOC_BORDER@
client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
-- }}}
